package rpg.client.player.swing;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import rpg.client.Instruction;
import rpg.client.model.Actor;
import rpg.client.model.Dialog;
import rpg.client.model.DialogResponse;

public class ChatJDialog extends JDialog implements ActionListener {
	public static void launch(final GameJPanel gjp, final Dialog dialog,
			final Actor actor) {
		final StartChat sc = new StartChat(gjp, dialog, actor);
		SwingUtilities.invokeLater(sc);
	}

	private final GameJPanel game;
	private final Dialog dialog;
	private final Actor actor;
	private final String playerID;

	ChatJDialog(final GameJPanel gjp, final Dialog d, final Actor a) {
		super();
		game = gjp;
		dialog = d;
		actor = a;
		playerID = gjp.getPlayerID();

		setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		this.setLayout(new BorderLayout());

		final AvatarPanel avatarPanel = new AvatarPanel(actor);
		add(avatarPanel, BorderLayout.WEST);

		final JPanel info = new InfoPanel(dialog, actor);
		add(info, BorderLayout.EAST);

		final ResponsePanel responses = new ResponsePanel(this, dialog);
		add(responses, BorderLayout.SOUTH);

		pack();
	}

	@Override
	public void actionPerformed(final ActionEvent e) {
		if (e.getSource() instanceof ResponseButton) {
			final ResponseButton rb = (ResponseButton) e.getSource();
			final String storyID = rb.getStoryID();
			if (storyID.length() > 0) {

			}
			game.request(Instruction.startChat(playerID, storyID,
					rb.getChatID(), ""));
		}

		setVisible(false);
		dispose();
	}
}

class InfoPanel extends JPanel {
	/**
     * 
     */
	private static final long serialVersionUID = 3743933813198887346L;

	InfoPanel(final Dialog dialog, final Actor actor) {
		super(new BorderLayout());
		add(new JLabel(dialog.getText()), BorderLayout.CENTER);
		add(new JLabel("[" + dialog.getMode() + "]"), BorderLayout.SOUTH);
	}
}

class ResponseButton extends JButton {
	/**
     * 
     */
	private static final long serialVersionUID = 7131414750777875613L;

	private final String storyID;
	private final String chatID;

	public ResponseButton(final ActionListener listener,
			final DialogResponse dr, final boolean oneEntry) {
		this(listener, dr.getStoryID(), dr.getChatID(), (oneEntry && (dr
				.getText().length() == 0)) ? "..." : dr.getText());
	}

	public ResponseButton(final ActionListener listener, final String storyID,
			final String chatID, final String text) {
		super(text);
		this.storyID = storyID;
		this.chatID = chatID;
		addActionListener(listener);
	}

	String getChatID() {
		return chatID;
	}

	String getStoryID() {
		return storyID;
	}
}

class ResponsePanel extends JPanel {
	/**
     * 
     */
	private static final long serialVersionUID = 439610329063779620L;

	ResponsePanel(final ActionListener listener, final Dialog dialog) {
		super(new GridLayout(Math.max(1, dialog.getResponses().size()), 1));
		if (dialog.getResponses().isEmpty()) {
			add(new ResponseButton(listener, "", "", "..."));
		} else if (dialog.getResponses().size() == 1) {
			final DialogResponse dr = dialog.getResponses().get(0);
			final ResponseButton rb = new ResponseButton(listener, dr, true);
			add(rb);
		} else {
			for (final DialogResponse dr : dialog.getResponses()) {
				final ResponseButton rb = new ResponseButton(listener, dr,
						false);
				add(rb);
			}
		}
	}
}

class StartChat implements Runnable {
	private final GameJPanel game;
	private final Dialog dialog;
	private final Actor actor;

	public StartChat(final GameJPanel gjp, final Dialog dialog2,
			final Actor actor2) {
		super();
		game = gjp;
		dialog = dialog2;
		actor = actor2;
	}

	@Override
	public void run() {
		final ChatJDialog cjd = new ChatJDialog(game, dialog, actor);
		cjd.setVisible(true);
	}
}
